Items in a grid can be selected both through end-user interactions and programmatically. The SelectionMode property defines how the items in a grid can be selected through end-user interactions. SelectionMode.Single indicates that only one item can be selected at a time. Multiple indicates that multiple items can be selected without pressing the CTRL or SHIFT modifier keys. Extended (default) indicates that multiple items can be selected by pressing the modifier keys.
|
CTRL-PageUp/PageDown will unselect any active selection and move to the first or last item, respectively. CTRL-HOME/END will also unselect any active selection; however, it will move to and select the first or last item, respectively. |
Retrieving the Selected Items
The selected data items can be retrieved through the SelectedItems property, which return all the data items that are currently selected, and the SelectedItem property, which returns the last data item that was selected.
|
The SelectedItem and SelectedItems properties can only be used with a synchronous data source. When used with a asynchronous data source, an exception will be thrown. |
<sldg:DataGridControl x:Name="sldgDataGridControl"
ItemsSource="{Binding Path=People}">
<sldg:DataGridControl.FixedFooters>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ElementName=sldgDataGridControl,
Path=SelectedItem.FirstName, StringFormat='{}{0} '}" />
<TextBlock Text="{Binding ElementName=sldgDataGridControl,
Path=SelectedItem.LastName, StringFormat='{}{0} '}" />
<TextBlock Text="{Binding ElementName=sldgDataGridControl,
Path=SelectedItems.Count, StringFormat='({0} items are selected)'}" />
</StackPanel>
</sldg:DataGridControl.FixedFooters>
</sldg:DataGridControl>
By using the BeginGetSelectedItems and EndGetSelectedItems asynchronous methods, the items that are currently selected in a grid can be retrieved. When dealing with a local data source (i.e., "full list"), the BeginGetSelectedItems method will return immediately and the value of the IsCompleted property of the returned IAsyncResult will be true indicating that the operation has been completed and the EndGetSelectedItems method can be called to finalize the process and get the selected items. If a virtualized data source is used, the EndGetSelectedItems method needs to be called in the callback after verifying whether the operation completed synchronously or not.
Retrieving the selected items asynchronously
Private Sub GetSelectedItems()
Dim result As IAsyncResult = Me.sldgDataGridControl.BeginGetSelectedItems( New AsyncCallback( AddressOf Me.ProcessSelectedItems ), Nothing )
If( result.IsCompleted ) Then
Dim selectedItems As IEnumerable( Of Object ) = Me.sldgDataGridControl.EndGetSelectedItems( result )
End If
End Sub
Private Sub ProcessSelectedItems( ByVal result As IAsyncResult )
If( result.CompletedSynchronously ) Then
Return
End If
Dim selectedItems As IEnumerable( Of Object ) = Me.sldgDataGridControl.EndGetSelectedItems( result )
End Sub
Private Sub DataGridControl_SelectionChanged( ByVal sender As Object, ByVal e As EventArgs )
Me.GetSelectedItems()
End Sub
private void GetSelectedItems()
{
IAsyncResult result = this.sldgDataGridControl.BeginGetSelectedItems( new AsyncCallback( this.ProcessSelectedItems ), null );
if( result.IsCompleted )
IEnumerable<object> selectedItems = this.sldgDataGridControl.EndGetSelectedItems( result );
}
private void ProcessSelectedItems( IAsyncResult result )
{
if( result.CompletedSynchronously )
return;
IEnumerable<object> selectedItems = this.sldgDataGridControl.EndGetSelectedItems( result );
}
private void DataGridControl_SelectionChanged( object sender, EventArgs e )
{
this.GetSelectedItems();
}
Selecting Items Programmatically
Items can be selected by adding selection ranges to a grid's SelectedRanges property. Each range that is added to the collection represents a group of items that have matched one or more selection criteria. Programmatically, a selection range can only be created if the data it is working with is sorted. In order to sort the data, one or more SortDescription objects, which will be used to create the data query that is sent to the data source, must be provided at construction.
A selection range defines "start" and "end" range-information dictionaries that specify the start and end points of a range of selected items (see StartRangeInfos and EndRangeInfos properties). For each start/end range-information dictionary combination that is added to the selection range, a corresponding sort description, whose PropertyName property value matches the key of the start/end range-information dictionary combination, must also be provided (see examples below).
|
The sort descriptions used by a selection range have no impact on how the data is actually sorted in the grid and vice-versa. |
In addition, both the start/end range-information dictionaries (i.e., StartRangeInfos and EndRangeInfos, respectively) expose an IsInclusive property that determines whether the start or end range-information dictionaries are inclusive, indicating that their values are included in the selection range (default), or if they are excluded from the selection range. These properties apply to all the range-information dictionary combinations specified in the StartRangeInfos and EndRangeInfos dictionaries.
Items from a local, synchronous data source can also be added to a selection range through the FromItem and ToItem methods, which are defined by the StartRangeInfos and EndRangeInfos dictionaries, and represent the item from which to start the selection range and the item at which the range ends, respectively (see Selecting from and to a specific item example below). When specifying a start and end item as the selection range, the items will be selected according to their position in the data source and not how they are displayed on screen. This means that all items between the start and end items will be selected, regardless of where the start and end items are located visually.
|
Predicates (i.e., filter parameter in the SelectionRange ctors) are executed locally meaning that when the BeginGetSelectedItems and EndGetSelectedItems are called and a selection range that provides a predicate is used, items will be retrieved from the server in order to determine those that pass the filter.
If one or more start and end range information is provided and/or a filter expression, only the items that are not already excluded by the range information and filter expression will be retrieved.
In a virtualized environment, it is not recommended to use the filter predicate unless dealing with a very limited number of items. |
Items can also be unselected by creating a selection range and setting its SelectionType property to Unselect (see Unselecting items from a selection range example below).
Now that you are thoroughly confused, take a look at the examples below, which cover most, if not all, possible scenarios.
Selecting all items
Me.sldgDataGridControl.SelectedRanges.Clear()
Me.sldgDataGridControl.SelectedRanges.Add( SelectionRange.All )
this.sldgDataGridControl.SelectedRanges.Clear();
this.sldgDataGridControl.SelectedRanges.Add( SelectionRange.All );
Selecting specific items (ShipCountry = "Germany")
Dim range As New SelectionRange( New SortDescription() { New SortDescription( "ShipCountry", ListSortDirection.Ascending ) }, Nothing, Nothing)
range.StartRangeInfos.Add( "ShipCountry", "Germany" )
range.EndRangeInfos.Add( "ShipCountry", "Germany" )
Me.sldgDataGridControl.SelectedRanges.Clear()
Me.sldgDataGridControl.SelectedRanges.Add( range )
SelectionRange range = new SelectionRange( new SortDescription[] { new SortDescription( "ShipCountry", ListSortDirection.Ascending ) }, null, null );
range.StartRangeInfos.Add( "ShipCountry", "Germany" );
range.EndRangeInfos.Add( "ShipCountry", "Germany" );
this.sldgDataGridControl.SelectedRanges.Clear();
this.sldgDataGridControl.SelectedRanges.Add( range );
Selecting items within a range (ShipCountry = "A-M")
Dim range As New SelectionRange( New SortDescription() { new SortDescription( "ShipCountry", ListSortDirection.Ascending ) }, Nothing, Nothing )
range.StartRangeInfos.Add( "ShipCountry", "A" )
range.EndRangeInfos.Add( "ShipCountry", "N" )
range.EndRangeInfos.IsInclusive = False
Me.sldgDataGridControl.SelectedRanges.Clear()
Me.sldgDataGridControl.SelectedRanges.Add( range )
SelectionRange range = new SelectionRange( new SortDescription[] { new SortDescription( "ShipCountry", ListSortDirection.Ascending ) }, null, null );
range.StartRangeInfos.Add( "ShipCountry", "A" );
range.EndRangeInfos.Add( "ShipCountry", "N" );
range.EndRangeInfos.IsInclusive = false;
this.sldgDataGridControl.SelectedRanges.Clear();
this.sldgDataGridControl.SelectedRanges.Add( range );
Selecting items using a filter expression (ShipVia !=3)
Dim expression As New FilterExpression( "ShipVia", FilterOperator.NotEqual, 3 )
Dim range As New SelectionRange( New SortDescription() { New SortDescription( "OrderDate", ListSortDirection.Ascending ) }, expression, Nothing )
range.StartRangeInfos.Add( "OrderDate", New DateTime( 2006, 01, 01 ) )
range.EndRangeInfos.Add( "OrderDate", New DateTime( 2006, 12, 31 ) )
Me.sldgDataGridControl.SelectedRanges.Clear()
Me.sldgDataGridControl.SelectedRanges.Add( range )
FilterExpression expression = new FilterExpression( "ShipVia", FilterOperator.NotEqual, 3 );
SelectionRange range = new SelectionRange( new SortDescription[] { new SortDescription( "OrderDate", ListSortDirection.Ascending ) }, expression, null );
range.StartRangeInfos.Add( "OrderDate", new DateTime( 2006, 01, 01 ) );
range.EndRangeInfos.Add( "OrderDate", new DateTime( 2006, 12, 31 ) );
this.sldgDataGridControl.SelectedRanges.Clear();
this.sldgDataGridControl.SelectedRanges.Add( range );
Selecting items using combined filter expressions (ShipVia = 3 OR OrderDate >= 2008/01/01)
Dim leftExpression As New FilterExpression( "ShipVia", FilterOperator.Equal, 3 )
Dim rightExpression As New FilterExpression( "OrderDate", FilterOperator.GreaterThanOrEqual, New DateTime( 2008, 01, 01 ) )
Dim expression As New OrFilterExpression( leftExpression, rightExpression )
Dim range As New SelectionRange( expression, Nothing )
Me.sldgDataGridControl.SelectedRanges.Clear()
Me.sldgDataGridControl.SelectedRanges.Add( range )
FilterExpression leftExpression = new FilterExpression( "ShipVia", FilterOperator.Equal, 3 );
FilterExpression rightExpression = new FilterExpression( "OrderDate", FilterOperator.GreaterThanOrEqual, new DateTime( 2008, 01, 01 ) );
OrFilterExpression expression = new OrFilterExpression( leftExpression, rightExpression );
SelectionRange range = new SelectionRange( expression, null );
this.sldgDataGridControl.SelectedRanges.Clear();
this.sldgDataGridControl.SelectedRanges.Add( range );
Selecting items using multiple selection-range infos (ShipVia = 2 AND OrderDate = 2006)
Dim range As New SelectionRange( New SortDescription() { New SortDescription( "ShipVia", ListSortDirection.Ascending ),
New SortDescription( "OrderDate", ListSortDirection.Ascending )}, Nothing, Nothing )
range.StartRangeInfos.Add( "ShipVia", 2 )
range.StartRangeInfos.Add( "OrderDate", New DateTime( 2006, 01, 01 ) )
range.EndRangeInfos.Add( "ShipVia", 2 )
range.EndRangeInfos.Add( "OrderDate", New DateTime( 2006, 12, 31 ) )
Me.sldgDataGridControl.SelectedRanges.Clear()
Me.sldgDataGridControl.SelectedRanges.Add( range )
SelectionRange range = new SelectionRange( new SortDescription[] { new SortDescription( "ShipVia", ListSortDirection.Ascending ),
new SortDescription( "OrderDate", ListSortDirection.Ascending )}, null, null );
range.StartRangeInfos.Add( "ShipVia", 2 );
range.StartRangeInfos.Add( "OrderDate", new DateTime( 2006, 01, 01 ) );
range.EndRangeInfos.Add( "ShipVia", 2 );
range.EndRangeInfos.Add( "OrderDate", new DateTime( 2006, 12, 31 ) );
this.sldgDataGridControl.SelectedRanges.Clear();
this.sldgDataGridControl.SelectedRanges.Add( range );
Selecting items using a predicate delegate (ShippedDate > RequiredDate)
Dim range As New SelectionRange( Nothing, New Predicate(Of Object)( IsPastRequiredDate ) )
Me.sldgDataGridControl.SelectedRanges.Clear()
Me.sldgDataGridControl.SelectedRanges.Add( range )
Private Function IsPastRequiredDate( ByVal value As Object ) As Boolean
Dim order As Order = CType( value, Order )
If order Is Nothing Then
return False
End If
Return ( order.ShippedDate > order.RequiredDate )
End Function
SelectionRange range = new SelectionRange( null, new Predicate<object>( IsPastRequiredDate ) );
this.sldgDataGridControl.SelectedRanges.Clear();
this.sldgDataGridControl.SelectedRanges.Add( range );
private bool IsPastRequiredDate( object value )
{
Order order = value as Order;
if( order == null )
return false;
return ( order.ShippedDate > order.RequiredDate );
}
Selecting items using multiple selection ranges (ShipCountry = "A-D" AND ShipCountry = "M-S")
Dim firstRange As New SelectionRange( New SortDescription() { New SortDescription( "ShipCountry", ListSortDirection.Ascending ) }, Nothing, Nothing )
Dim secondRange As New SelectionRange( New SortDescription() { New SortDescription( "ShipCountry", ListSortDirection.Ascending ) }, Nothing, Nothing )
firstRange.StartRangeInfos.Add( "ShipCountry", "A" )
firstRange.EndRangeInfos.Add( "ShipCountry", "D" )
secondRange.StartRangeInfos.Add( "ShipCountry", "M" )
secondRange.EndRangeInfos.Add( "ShipCountry", "S" )
Me.sldgDataGridControl.SelectedRanges.Clear()
Me.sldgDataGridControl.SelectedRanges.Add( firstRange )
Me.sldgDataGridControl.SelectedRanges.Add( secondRange )
SelectionRange firstRange = new SelectionRange( new SortDescription[] { new SortDescription( "ShipCountry", ListSortDirection.Ascending ) }, null, null );
SelectionRange secondRange = new SelectionRange( new SortDescription[] { new SortDescription( "ShipCountry", ListSortDirection.Ascending ) }, null, null );
firstRange.StartRangeInfos.Add( "ShipCountry", "A" );
firstRange.EndRangeInfos.Add( "ShipCountry", "D" );
secondRange.StartRangeInfos.Add( "ShipCountry", "M" );
secondRange.EndRangeInfos.Add( "ShipCountry", "S" );
this.sldgDataGridControl.SelectedRanges.Clear();
this.sldgDataGridControl.SelectedRanges.Add( firstRange );
this.sldgDataGridControl.SelectedRanges.Add( secondRange );
Selecting items from start to specified end point
Dim range As New SelectionRange( New SortDescription() { New SortDescription( "ShipCountry", ListSortDirection.Ascending ) }, Nothing, Nothing )
' Select all items from the start to "C". All items that start with "A" or "B" will be selected.
' Using "B" only would not work since, for example, "Belgium" > "B".
range.StartRangeInfos.FromStart()
range.EndRangeInfos.Add( "ShipCountry", "C" )
range.EndRangeInfos.IsInclusive = False
Me.sldgDataGridControl.SelectedRanges.Clear()
Me.sldgDataGridControl.SelectedRanges.Add( range )
SelectionRange range = new SelectionRange( new SortDescription[] { new SortDescription( "ShipCountry", ListSortDirection.Ascending ) }, null, null );
// Select all items from the start to "C". All items that start with "A" or "B" will be selected.
// Using "B" only would not work since, for example, "Belgium" > "B".
range.StartRangeInfos.FromStart();
range.EndRangeInfos.Add( "ShipCountry", "C" );
range.EndRangeInfos.IsInclusive = false;
this.sldgDataGridControl.SelectedRanges.Clear();
this.sldgDataGridControl.SelectedRanges.Add( range );
Selecting items from specified start point to end
Dim range As New SelectionRange( New SortDescription() { New SortDescription( "ShipCountry", ListSortDirection.Ascending ) }, Nothing, Nothing )
range.StartRangeInfos.Add( "ShipCountry", "B" )
range.EndRangeInfos.ToEnd()
Me.sldgDataGridControl.SelectedRanges.Clear()
Me.sldgDataGridControl.SelectedRanges.Add( range )
SelectionRange range = new SelectionRange( new SortDescription[] { new SortDescription( "ShipCountry", ListSortDirection.Ascending ) }, null, null );
range.StartRangeInfos.Add( "ShipCountry", "B" );
range.EndRangeInfos.ToEnd();
this.sldgDataGridControl.SelectedRanges.Clear();
this.sldgDataGridControl.SelectedRanges.Add( range );
"Unselecting" items from a selection range
Dim range As New SelectionRange( New SortDescription() { New SortDescription( "ShipCountry", ListSortDirection.Ascending ) }, Nothing, Nothing )
range.SelectionType = SelectionType.Unselection
range.StartRangeInfos.Add( "ShipCountry", "Canada" )
range.EndRangeInfos.Add( "ShipCountry", "Canada" )
sldgDataGridControl.SelectedRanges.Add( range )
SelectionRange range = new SelectionRange( new SortDescription[] { new SortDescription( "ShipCountry", ListSortDirection.Ascending ) }, null, null );
range.SelectionType = SelectionType.Unselection;
range.StartRangeInfos.Add( "ShipCountry", "Canada" );
range.EndRangeInfos.Add( "ShipCountry", "Canada" );
sldgDataGridControl.SelectedRanges.Add( range );
Selecting from and to a specific item (LOCAL LIST ONLY)
Dim range As New SelectionRange()
range.StartRangeInfos.FromItem( Me.People[ 5 ] )
range.EndRangeInfos.ToItem( Me.People[ 10 ] )
sldgDataGridControl.SelectedRanges.Add( range )
SelectionRange range = new SelectionRange();
range.StartRangeInfos.FromItem( this.People[ 5 ] );
range.EndRangeInfos.ToItem( this.People[ 10 ] );
sldgDataGridControl.SelectedRanges.Add( range );
Selecting a single item from a remote data source (WCF DataServiceQuery)
Public Sub GetOrder( ByVal orderID As Integer )
Dim query As DataServiceQuery( Of Order )= TryCast( Data.Orders.Where( order => order.OrderID = orderID ), DataServiceQuery( Of Order ) )
If Not query Is Nothing Then
Dim result As IAsyncCallback= query.BeginExecute( New AsyncCallback( AddressOf Me.ProcessItem ), query )
End If
End Sub
Private Sub ProcessItem( Dim result As IAsyncResult )
Dim query As DataServiceQuery( Of Order )= TryCast( result.AsyncState, DataServiceQuery( Of Order )
If Not query Is Nothing Then
Dim q As IEnumerable( Of Order ) = query.EndExecute( result )
Dim order As Order = q.FirstOrDefault()
Dim range = New SelectionRange( order )
sldgDataGridControl.SelectedRanges.Clear()
sldgDataGridControl.SelectedRanges.Add( range )
End If
End Sub
Private Sub Button_Click( ByVal sender As Object, ByVal e As RoutedEventArgs )
Dim orderIDString As String = orderIDTextBox.Text.Trim()
If Not string.IsNullOrWhiteSpace( orderIDString ) Then
Me.GetOrder( System.Convert.ToInt32( orderIDString ) )
End If
End Sub
public void GetOrder( int orderID )
{
DataServiceQuery<Order> query = Data.Orders.Where( order => order.OrderID == orderID ) as DataServiceQuery<Order>;
if( query != null )
IAsyncResult result = query.BeginExecute( new AsyncCallback( this.ProcessItem ), query );
}
private void ProcessItem( IAsyncResult result )
{
DataServiceQuery<Order> query = result.AsyncState as DataServiceQuery<Order>;
if( query != null )
{
IEnumerable<Order> q = query.EndExecute( result );
Order order = q.FirstOrDefault();
SelectionRange range = new SelectionRange( order );
sldgDataGridControl.SelectedRanges.Clear();
sldgDataGridControl.SelectedRanges.Add( range );
}
}
private void Button_Click( object sender, RoutedEventArgs e )
{
string orderIDString = orderIDTextBox.Text.Trim();
if( !string.IsNullOrWhiteSpace( orderIDString ) )
this.GetOrder( System.Convert.ToInt32( orderIDString ) );
}
Selection-Changed Notifications
Selection-changed notifications are provided via the SelectionChanged event, which is raised whenever the selection in a grid changes whether by end-user interaction or through programmatic modifications of the selected ranges.